/*
 * Copyright 2012 Benoît Combe <benoit.combe@gmail.com>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package fr.ipst.spot.formulaires;

import fr.ipst.spot.exceptions.SpotExceptionForm;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 *
 * @author Benoît Combe <benoit.combe@gmail.com>
 */
public abstract class FormAbstract implements Serializable {

    private final String regexEmail = "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}";
    private final char[] accentuees = {'à', 'â', 'é', 'è', 'ê', 'ë', 'î', 'ï', 'ô', 'ö', 'ù', 'û', 'ü'};
    private final char[] ponctutation = {',', '?', ';', ':', '!', '\'', '"', '&'};
    private final int idMax = Integer.MAX_VALUE;
    private final String regexIdLDAP = "*";
    /**
     *
     */
    protected String msgErreurValidate = "";

    private void isLengthInf(String aTester, int nombreDeSignes) throws SpotExceptionForm {

        String msgErreur = " doit comporter " + nombreDeSignes + " caractères au maximum";

        if (aTester == null) {
            throw new SpotExceptionForm(msgErreur);
        }

        if (aTester.length() > nombreDeSignes) {
            throw new SpotExceptionForm(msgErreur);
        }
    }

    private void isLengthSup(String aTester, int nombreDeSignes) throws SpotExceptionForm {

        String msgErreur = " doit comporter " + nombreDeSignes + " caractères au minimum";

        if (aTester == null) {
            throw new SpotExceptionForm(msgErreur);
        }

        if (aTester.length() <= nombreDeSignes) {
            throw new SpotExceptionForm(msgErreur);
        }
    }

    private void isLengthEqual(String aTester, int nombreDeSignes) throws SpotExceptionForm {

        String msgErreur = " doit comporter " + nombreDeSignes + " caractères";

        if (aTester == null) {
            throw new SpotExceptionForm(msgErreur);
        }

        if (aTester.length() != nombreDeSignes) {
            throw new SpotExceptionForm(msgErreur);
        }
    }

    private void isLengthBeetween(String aTester, int min, int max) throws SpotExceptionForm {

        String msgErreur = " doit comporter entre " + min + " et " + max + " caractères";

        if (aTester == null) {
            throw new SpotExceptionForm(msgErreur);
        }

        if (aTester.length() < min && aTester.length() > max) {
            throw new SpotExceptionForm(msgErreur);
        }
    }

    private void isNonAccent(String aTester) throws SpotExceptionForm {

        for (char c : this.accentuees) {
            if (aTester.contains("" + c)) {
                throw new SpotExceptionForm(" ne doit pas contenir de caractère accentué");
            }
        }
    }

    private void isNonPonctuation(String aTester) throws SpotExceptionForm {

        for (char c : this.ponctutation) {
            if (aTester.contains("" + c)) {
                throw new SpotExceptionForm(" ne doit pas contenir de caractère de ponctuation");
            }
        }
    }

    private void isWithoutReturn(String aTester) throws SpotExceptionForm {

        if (aTester.contains("\n") || aTester.contains("\r")) {
            throw new SpotExceptionForm(" ne doit pas contenir de retour à la ligne");
        }
    }

    private void isNonSpace(String aTester) throws SpotExceptionForm {
        if (aTester.contains(" ")) {
            throw new SpotExceptionForm(" ne doit pas contenir d'espace");
        }
    }

    private void isNotEmpty(String aTester) throws SpotExceptionForm {
        String msg = " ne doit pas être vide";
        if (aTester == null) {
            throw new SpotExceptionForm(msg);
        }
        if (aTester.isEmpty()) {
            throw new SpotExceptionForm(msg);
        }
    }

    private void isNumeric(String aTester) throws SpotExceptionForm {
        String msg = " ne doit contenir que des nombres.";
        try {
            Double.parseDouble(aTester);
        } catch (NumberFormatException e) {
            throw new SpotExceptionForm(msg);
        } catch (NullPointerException e) {
            throw new SpotExceptionForm(msg);
        }
    }

    private void makeErreurMsg(SpotExceptionForm ex, String nomChamp) throws SpotExceptionForm {
        throw new SpotExceptionForm("Le champ " + nomChamp + ex.getMessage());
    }

    /**
     *
     * @param ex
     */
    protected void concatErreurMsg(SpotExceptionForm ex) {
        this.msgErreurValidate += ex.getMessage() + "ùù";
    }

    /**
     *
     * @param aTester
     * @param nomChamp
     * @throws SpotExceptionForm
     */
    protected void isDefaultLengthOneLine(String aTester, String nomChamp) throws SpotExceptionForm {
        try {
            this.isNotEmpty(aTester);
        } catch (SpotExceptionForm ex) {
            this.makeErreurMsg(ex, nomChamp);
        }
        try {
            this.isLengthInf(aTester, 45);
        } catch (SpotExceptionForm ex) {
            this.makeErreurMsg(ex, nomChamp);
        }
        try {
            this.isWithoutReturn(aTester);
        } catch (SpotExceptionForm ex) {
            this.makeErreurMsg(ex, nomChamp);
        }
    }

    /**
     *
     * @param aTester
     * @throws SpotExceptionForm
     */
    private void isIntegerBeetween(Integer aTester, Integer min, Integer max) throws SpotExceptionForm {
        String msg = "doit être compris entre " + min + " et " + max;
        if (aTester == null) {
            throw new SpotExceptionForm(msg);
        }
        if (aTester < min || aTester > max) {
            throw new SpotExceptionForm(msg);
        }
    }

    private void isFloatBeetween(Float aTester, Float min, Float max) throws SpotExceptionForm {
        String msg = "doit être compris entre " + min + " et " + max;
        if (aTester == null) {
            throw new SpotExceptionForm(msg);
        }
        if (aTester < min || aTester > max) {
            throw new SpotExceptionForm(msg);
        }
    }

    private void isRegExMatched(String aTester, String regExp, String msgError) throws SpotExceptionForm {
        if (!aTester.matches(regExp)) {
            throw new SpotExceptionForm(msgError);
        }
    }

    /**
     *
     * @param aTester
     * @throws SpotExceptionForm
     */
    protected void isId(Integer aTester) throws SpotExceptionForm {
        this.isIntegerBeetween(aTester, 1, idMax);
    }

    /**
     *
     * @param aTester
     * @param nomChamp
     * @throws SpotExceptionForm
     */
    protected void isNomFichier(String aTester, String nomChamp) throws SpotExceptionForm {

        try {
            this.isLengthInf(aTester, 255);
            this.isNonAccent(aTester);
            this.isNonPonctuation(aTester);
            this.isWithoutReturn(aTester);
            this.isNonSpace(aTester);
        } catch (SpotExceptionForm ex) {
            this.makeErreurMsg(ex, nomChamp);
        }
    }

    /**
     *
     * @param aTester
     * @param nomChamp
     * @throws SpotExceptionForm
     */
    protected void isLongText(String aTester, String nomChamp) throws SpotExceptionForm {
        try {
            this.isLengthInf(aTester, 10000);
            this.isNotEmpty(aTester);
        } catch (SpotExceptionForm ex) {
            this.makeErreurMsg(ex, nomChamp);
        }
    }

    /**
     *
     * @param aTester
     * @throws SpotExceptionForm
     */
    protected void isTitreDocument(String aTester) throws SpotExceptionForm {
        try {
            this.isLengthBeetween(aTester, 1, 255);
        } catch (SpotExceptionForm e) {
            this.makeErreurMsg(e, "titre");
        }
    }

    /**
     *
     * @param aTester
     * @param nomChamp
     * @throws SpotExceptionForm
     */
    protected void isUrl(String aTester, String nomChamp) throws SpotExceptionForm {
        try {
            this.isLengthInf(aTester, 255);
            this.isNonAccent(aTester);
            this.isNonSpace(aTester);
            this.isNotEmpty(aTester);
        } catch (SpotExceptionForm ex) {
            this.makeErreurMsg(ex, nomChamp);
        }
        if (!aTester.startsWith("http://")) {
            throw new SpotExceptionForm("Le champ " + nomChamp + " doit commencer par \"http://\"");
        }
    }

    /**
     *
     * @param aTester
     * @throws SpotExceptionForm
     */
    protected void isEmailAdresse(String aTester) throws SpotExceptionForm {
        try {
            this.isLengthInf(aTester, 255);
            this.isNonAccent(aTester);
            this.isNotEmpty(aTester);
            this.isNonSpace(aTester);
            this.isRegExMatched(aTester, regexEmail, "L'adresse email fournie n'est pas valide");
        } catch (SpotExceptionForm e) {
            throw new SpotExceptionForm("L'adresse email fournie n'est pas valide");
        }
    }

    /**
     *
     * @param aTester
     * @throws SpotExceptionForm
     */
    protected void isCodePostal(Integer aTester) throws SpotExceptionForm {
        try {
            this.isIntegerBeetween(aTester, 1, 100000);
        } catch (SpotExceptionForm e) {
            throw new SpotExceptionForm("Le champ Code Postal est invalide");
        }
    }

    /**
     *
     * @param aTester
     * @throws SpotExceptionForm
     */
    protected void isFax(String aTester) throws SpotExceptionForm {
        try {
            this.isNotEmpty(aTester);
            this.isNumeric(aTester);
        } catch (SpotExceptionForm e) {
            throw new SpotExceptionForm("Le champ Fax " + e.getMessage());
        }
    }

    /**
     *
     * @param aTester
     * @param nomChamp
     * @throws SpotExceptionForm
     */
    protected void isPhoneNumber(String aTester, String nomChamp) throws SpotExceptionForm {
        try {
            this.isLengthBeetween(aTester, 5, 17);
            aTester = aTester.replace("(", "");
            aTester = aTester.replace(")", "");
            aTester = aTester.replace("+", "");
            aTester = aTester.replace(" ", "");
            aTester = aTester.replace("-", "");
            aTester = aTester.replace(".", "");
            aTester = aTester.replace("_", "");
            this.isNumeric(aTester);
        } catch (SpotExceptionForm e) {
            throw new SpotExceptionForm("Le champ " + nomChamp + e.getMessage());
        }
    }

    /**
     *
     * @param aTester
     * @param nomChamp
     * @throws SpotExceptionForm
     */
    protected void isHourAm(Integer aTester, String nomChamp) throws SpotExceptionForm {
        try {
            this.isIntegerBeetween(aTester, -1, 12);
        } catch (SpotExceptionForm e) {
            throw new SpotExceptionForm("L'heure donnée pour le créneau " + nomChamp + " est invalide");
        }
    }

    /**
     *
     * @param aTester
     * @param nomChamp
     * @throws SpotExceptionForm
     */
    protected void isHourPm(Integer aTester, String nomChamp) throws SpotExceptionForm {
        try {
            this.isIntegerBeetween(aTester, 11, 23);
        } catch (SpotExceptionForm e) {
            throw new SpotExceptionForm("L'heure donnée pour le créneau " + nomChamp + " est invalide");
        }
    }

    /**
     *
     * @param aTester
     * @param nomChamp
     * @throws SpotExceptionForm
     */
    protected void isMinutes(Integer aTester, String nomChamp) throws SpotExceptionForm {
        try {
            this.isIntegerBeetween(aTester, -1, 60);
        } catch (SpotExceptionForm e) {
            throw new SpotExceptionForm("Les minutes données pour le créneau " + nomChamp + " sont invalides");
        }
    }

    /**
     *
     * @param aTeseter
     * @throws SpotExceptionForm
     */
    protected void isDateDeNaissnce(String aTeseter) throws SpotExceptionForm {
        DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
        try {
            Date date = format.parse(aTeseter);
            if (!date.before(GregorianCalendar.getInstance().getTime())) {
                throw new SpotExceptionForm("La date de naissance donnée est invalide");
            }
        } catch (ParseException ex) {
            throw new SpotExceptionForm("La date de naissance donnée est invalide");
        }
    }

    /**
     *
     * @param aTester
     * @throws SpotExceptionForm
     */
    protected void isNumSs(String aTester) throws SpotExceptionForm {
        try {
            this.isLengthEqual(aTester, 15);
            this.isNumeric(aTester);
            Long num = new Long(aTester.substring(0, 13));
            Integer cle = new Integer(aTester.substring(13, 15));
            if ((97 - (num % 97)) != cle) {
                throw new SpotExceptionForm("Format Invalide");
            }
        } catch (SpotExceptionForm e) {
            throw new SpotExceptionForm("Le n° de sécurité sociale fourni est invalide :" + e.getMessage());
        }
    }

    /**
     *
     * @param aTester
     * @throws SpotExceptionForm
     */
    protected void isIdLDAP(String aTester) throws SpotExceptionForm {
        this.isRegExMatched(aTester, regexIdLDAP, "L'identifiant LDAP fournit est invalide");
    }

    /**
     *
     * @param aTester
     * @param nomChamp
     * @throws SpotExceptionForm
     */
    protected void isString255CharsNonEmpty(String aTester, String nomChamp) throws SpotExceptionForm {
        try {
            this.isLengthBeetween(aTester, 1, 255);
        } catch (SpotExceptionForm e) {
            this.makeErreurMsg(e, nomChamp);
        }
    }
}
